package com.molichuxing.gateway.bff.permission.services.impl;

import com.alibaba.fastjson.JSONObject;
import com.moli.iov.util.Md5PwdEncoder;
import com.moli.iov.util.api.ApiUtils;
import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.result.ResponseCodeEnum;
import com.molichuxing.framework.result.ResponseResult;
import com.molichuxing.framework.utils.*;
import com.molichuxing.gateway.bff.permission.convertor.Convert;
import com.molichuxing.gateway.bff.permission.entity.response.*;
import com.molichuxing.gateway.bff.permission.services.AccountBffService;
import com.molichuxing.gateway.property.EmailSubjectEnum;
import com.molichuxing.gateway.property.SystemNameEnum;
import com.molichuxing.gateway.utils.OpEmailUtil;
import com.molichuxing.gateway.utils.SSOTokenUtil;
import com.molichuxing.gateway.utils.TokenUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.response.AccountLoginBizDto;
import com.molichuxing.services.business.service.AccountBizService;
import com.molichuxing.services.business.service.SmsBizService;
import com.molichuxing.services.infrastructure.dto.request.create.IovCreateAccountDto;
import com.molichuxing.services.infrastructure.dto.request.create.IpDetail;
import com.molichuxing.services.infrastructure.dto.request.modify.IovModifyAccountDto;
import com.molichuxing.services.infrastructure.dto.response.DealerDto;
import com.molichuxing.services.infrastructure.dto.response.IovAccountDto;
import com.molichuxing.services.infrastructure.dto.response.response.*;
import com.molichuxing.services.infrastructure.service.*;
import com.molichuxing.services.property.LoginLogTypeEnum;
import com.molichuxing.services.property.OpIovStatusConvertEnum;
import com.molichuxing.services.property.SmsTemplateEnum;
import com.molichuxing.services.property.SystemTypeEnum;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service("permissionBffService")
public class AccountBffServiceImpl implements AccountBffService {
    private static final Logger logger = LoggerFactory.getLogger(AccountBffServiceImpl.class);

    @Resource
    private TokenUtil tokenUtil;

    @Resource
    private SSOTokenUtil ssoTokenUtil;

    @Resource
    private AccountBizService accountBizService;

    @Resource
    private AccountDealerService accountDealerService;

    @Resource
    private DealerService dealerService;

    @Resource
    private AccountGroupService accountGroupService;

    @Resource
    private AccountService accountService;

    @Resource
    private IpService ipService;

    @Value("${password.salt}")
    private String passwordSalt;

    @Resource
    private IovPermissionService iovPermissionService;

    @Resource
    private OpEmailUtil emailUtil;

    @Resource
    private LoginLogService loginLogService;

    @Resource
    private SmsBizService smsBizService;

    @Resource
    private ResourceService resourceService;

    @Value("${op.account.suffix}")
    private String opAccountSuffix; //op用户登录名后缀

    @Value("${profiles.active.explain}")
    private String active;

    /**
     * 账号登录
     *
     * @param params account：账号 <br/>
     *               password：密码 <br/>
     *               systemType：系统类型-enum <br/>
     * @return
     * @throws BizException
     * @throws Exception
     */
    @Override
    public AccountLoginVo login(Map<String, Object> params) throws BizException, Exception {
        AccountLoginVo result = null;
        // 登录
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String requestIp = IpUtil.getIpAddr(request);
        params.put("requestIp", requestIp); //请求者ip

        //根据ip获取地址
        StringBuffer ipAddress = new StringBuffer();
        try {
            IpDetail ipDetail = ipService.getIpDetail(requestIp);
            if (ipDetail != null) {
                String country = ipDetail.getCountry() == null ? "" : ipDetail.getCountry(); //国家
                String region = ipDetail.getRegion() == null ? "" : ipDetail.getRegion(); //省份、直辖市
                String city = ipDetail.getCity() == null ? "" : ipDetail.getCity(); //城市
                ipAddress.append(country);
                ipAddress.append(region);
                ipAddress.append(!region.equals(city) ? city : "");
            }
        } catch (Exception e) {
            logger.error("根据ip获取地址异常");
            logger.error(e.getMessage(), e);
        }
        // 请求ip所属地
        params.put("requestIpAddress", ipAddress.toString());

        // 获取浏览器信息
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        // 发起请求浏览器
        params.put("browser", browser.getName());


        AccountLoginBizDto accountLoginBizDto = accountBizService.login(params);

        //生成单点登陆token，直接返回
        String ssoToken = ssoTokenUtil.generateSsoTokenAndHead(accountLoginBizDto.getAccount());

        UserEntity user = Convert.toUserEntity(accountLoginBizDto);
        user.setSsoToken(ssoToken);
        // 删除redis中存在的该账户信息
        tokenUtil.deleteUserByAccount(user.getAccount());
        // 生成本地token，保存redis
        tokenUtil.setUserToken(user);


        result = Convert.toAccountLoginVo(accountLoginBizDto);
        result.setToken(ssoToken);
        result.setLoginIp(requestIp);
        result.setLoginArea(ipAddress.toString());

        return result;
    }

    /**
     * 账号登录
     *
     * @param params account：账号 <br/>
     *               password：密码 <br/>
     *               systemType：系统类型-enum <br/>
     * @return
     * @throws BizException
     * @throws Exception
     */
    @Override
    public AccountLoginVo loginByIov(Map<String, Object> params) throws BizException, Exception {
        AccountLoginVo result = null;
        // 登录
        AccountLoginBizDto accountLoginBizDto = accountBizService.loginByIov(params);

        UserEntity user = Convert.toUserEntity(accountLoginBizDto);

        //生成单点登陆token，直接返回
        String ssoToken = ssoTokenUtil.generateSsoTokenAndHead(user.getAccount());
        user.setSsoToken(ssoToken);

        // 删除redis中存在的该账户信息
        tokenUtil.deleteUserByAccount(user.getAccount());
        // 生成本地token，保存redis
        tokenUtil.setUserToken(user);


        result = Convert.toAccountLoginVo(accountLoginBizDto);
        result.setToken(ssoToken);

        return result;
    }

    @Override
    public Paged<AccountVo> getAccountList(Map<String, Object> param, int pageNum, int pageSize) {

        //1，根据条件查询出符合条件的基本用户数据
        //2，判断查询的用户类型
        //	->如果是op用户，那么查询用户绑定的op角色和车联网角色
        //	->如果是经销商用户，那么查询用户绑定的经销商角色和经销商名称
        return editorAccountVo(accountBizService.getAccountList(param, pageNum, pageSize), Integer.parseInt(param.get("systemType").toString()));
    }

    /**
     * 补全AccountVo的数据
     * ->如果是op用户，那么查询用户绑定的op角色和车联网角色
     * ->如果是经销商用户，那么查询用户绑定的经销商角色和经销商名称
     *
     * @param pageList
     * @param systemType
     */
    private Paged<AccountVo> editorAccountVo(Paged<AccountDto> pageList, int systemType) {
        Paged<AccountVo> result = new Paged<>();
        if (pageList != null) {
            List<AccountDto> dataList = pageList.getList();

            final List<AccountVo> resultDataList = new ArrayList<AccountVo>();
            if (CollectionUtils.isNotEmpty(dataList)) {
                final List<Integer> accountIdList = new ArrayList<>();
                final List<String> emailList = new ArrayList<>();
                dataList.forEach(account -> {
                    accountIdList.add(account.getId());
                    resultDataList.add(Convert.toAccountVo(account));
                    emailList.add(account.getAccount());
                });

                //2
                if (systemType == SystemTypeEnum.DEALER.getValue()) { //查询账号绑定得经销商
                    Map<String, Object> getAccountDealerParam = new HashMap<>();
                    getAccountDealerParam.put("accountIds", accountIdList);
                    List<AccountDealerDto> accountDealerList = accountDealerService.getAccountDealerByParam(getAccountDealerParam);
                    if (CollectionUtils.isNotEmpty(accountDealerList)) {

                        final List<Integer> dealerIdList = new ArrayList<>();
                        accountDealerList.forEach(accountDealer -> {
                            if (accountDealer.getDealerId() != null && accountDealer.getDealerId() > 0) {
                                dealerIdList.add(accountDealer.getDealerId());
                            }
                        });

                        Map<Integer, DealerDto> dealerMap = null;
                        if (CollectionUtils.isNotEmpty(dealerIdList)) {
                            Map<String, Object> getDealerParam = new HashMap<>();
                            getDealerParam.put("dealerIds", dealerIdList);
                            List<DealerDto> dealerList = dealerService.getDealerListByParam(getDealerParam);
                            if (CollectionUtils.isNotEmpty(dealerList)) {
                                dealerMap = dealerList.stream().collect(Collectors.toMap(DealerDto::getDealerId, dealerDto -> dealerDto));
                            }
                        }
                        final Map<Integer, DealerDto> accountBindDealerMap = new HashMap<>();
                        if (dealerMap != null && dealerMap.size() > 0) {
                            for (AccountDealerDto accountDealer : accountDealerList) {
                                DealerDto dto = null;
                                if ((dto = dealerMap.get(accountDealer.getDealerId())) != null) {
                                    accountBindDealerMap.put(accountDealer.getAccountId(), dealerMap.get(accountDealer.getDealerId()));
                                }
                            }
                        }

                        resultDataList.forEach(accountVo -> {
                            DealerDto dto = null;
                            if ((dto = accountBindDealerMap.get(accountVo.getId())) != null) {
                                accountVo.setDealerId(dto.getDealerId());
                                accountVo.setDealerName(dto.getShortName());
                            }

                        });
                    }
                } else { //OP账号，查询绑定得车联网角色
                    List<IovAccountDto> iovAccoutList = null;
                    try {
                        iovAccoutList = iovPermissionService.getAccountList(emailList);
                    } catch (Exception e) {
                        logger.error("调用车联网获取用户俩表异常  " +e.getMessage(), e);
                    }

                    Map<String, IovAccountDto> iovAccountMap = null;
                    if (CollectionUtils.isNotEmpty(iovAccoutList)) {
                        iovAccountMap = iovAccoutList.stream().collect(Collectors.toMap(IovAccountDto :: getEmail, iovAccount -> iovAccount));
                    }

                    if (iovAccountMap != null && iovAccountMap.size() > 0) {
                        for (AccountVo account : resultDataList) {
                            IovAccountDto dto = null;
                            if ((dto = iovAccountMap.get(account.getAccount())) != null) {
                                account.setIovGroupName(dto.getRoleName()); //车联网角色名称
                            }
                        }
                    }
                }
            }
            result.setList(resultDataList);
            result.setTab(pageList.getTab());
            result.setTotal(pageList.getTotal());
            result.setPageSize(pageList.getPageSize());
        }

        return result;
    }

    @Override
    public ResponseResult<Boolean> createAccount(AccountCreateVo newAccount) {
        //添加新用户
        //如果是op用户
        //添加用户 -> 添加用户与角色的关联 ->  发送邮件 ->发送短信
        //            添加用户与车联网角色关联
        //如果是经销商用户
        //添加用户 -> 添加用户与角色的关联 ->  发送邮件 ->发送短信
        //            添加用户与经销商的关联
        ResponseResult<Boolean> result = validateCreateParam(newAccount);
        if (result != null) {
            return result;
        }
        result = new ResponseResult<>();

        try {
            //查询账号是否存在
            Map<String, Object> getAccountCountParam = new HashMap<>();
            getAccountCountParam.put("account", newAccount.getAccount());
            getAccountCountParam.put("systemType", newAccount.getSystemType());
            int count = accountService.getAccountCount(getAccountCountParam);
            if (count > 0) {
                logger.error("用户已经存在，无法重复保存，account is :: {}", newAccount.getAccount());
                return result.error("保存失败，用户[" + newAccount.getAccount() + "]已经存在");
            }

            UserEntity currentLoginUser = tokenUtil.getUser();

            String password = ApiUtils.generateNonceStrLower(8);
            AccountCreateDto accountDto = Convert.toAccountCreateDto(newAccount);
            accountDto.setPassword(Md5PwdEncoder.encodePassword(password, passwordSalt));
            accountDto.setAccountId(currentLoginUser.getAccountId()); //操作人id
            if (accountDto.getSystemType() == SystemTypeEnum.OP.getValue()) { //op系统用户
                accountDto.setAccountAccount(currentLoginUser.getRealName()); //操作人名字
            } else { //经销商系统用户
                accountDto.setAccountAccount("系统"); //操作人名字，op添加的经销商用户默认给 “系统”
            }
            accountDto.setPasswordSalt(passwordSalt);
            int accountId = accountService.createAccount(accountDto);
            if (accountId > 0) {
                //绑定用户与角色的关联关系
                if (newAccount.getGroupId() != null && newAccount.getGroupId() > 0) {
                    AccountGroupDto accountGroup = new AccountGroupDto();
                    accountGroup.setAccountId(accountId);
                    accountGroup.setGroupId(newAccount.getGroupId());
                    accountGroup.setGmtCreate(LocalDateTime.now());
                    accountGroupService.createBatchAccountGroup(accountGroup);
                }

                //如果是经销商，添加数据到经销商关联关系表
                if (newAccount.getSystemType() == SystemTypeEnum.DEALER.getValue()) {
                    AccountDealerDto accountDealer = new AccountDealerDto();
                    accountDealer.setAccountId(accountId);
                    accountDealer.setDealerId(newAccount.getDealerId());
                    accountDealerService.createAccountDealer(accountDealer);
                } else {
                    try { //添加用户到车联网
                        IovCreateAccountDto iovCreateDto = new IovCreateAccountDto();
                        iovCreateDto.setEmail(newAccount.getAccount());
                        iovCreateDto.setRealName(newAccount.getRealName());
                        iovCreateDto.setUserPhone(newAccount.getUserPhone());
                        iovCreateDto.setStatus(OpIovStatusConvertEnum.getIovValue(newAccount.getStatus()));
                        iovCreateDto.setRoleId(newAccount.getIovGroupId());
                        iovCreateDto.setPassword(Md5PwdEncoder.encodePassword(password, passwordSalt));
                        ResponseResult<Boolean> iovResult = iovPermissionService.createAccount(iovCreateDto);
                        if (!iovResult.getCode().equals(ResponseCodeEnum.SUCCESS.getCode()) || !iovResult.getData()) { //同步失败
                            logger.error("添加用户报错，op添加用户成功，同步到车联网失败，用户id :: {}, 返回信息result ::{}", accountId, iovResult.getMessage());
                            return result.error("新用户同步到车联网失败，车联网返回信息：" + iovResult.getMessage());
                        }
                    } catch (Exception e) {
                        logger.error("添加用户报错，op添加用户成功，同步到车联网失败，用户id :: {}", accountId);
                        logger.error(e.getMessage(), e);
                        return result.error("新用户同步到车联网失败");
                    }
                }

                //OP发送邮件，发送短信
                if (newAccount.getSystemType() == SystemTypeEnum.OP.getValue()) {
                    String emailContent = emailUtil.editorCreateOpAccountSuccessContent(newAccount.getAccount(), password);
                    boolean sendResult = emailUtil.send(EmailSubjectEnum.CREATE_OP_ACCOUNT_SUCCESS.getName(), emailContent, newAccount.getAccount());
                    if (!sendResult) { //失败
                        String errorEmailContent = emailUtil.editorCreateAccountErrorContent(SystemNameEnum.OP_AND_IOV, newAccount.getRealName());
                        boolean errorEmailResult = emailUtil.send(newAccount.getRealName() + EmailSubjectEnum.CREATE_ACCOUNT_ERROR.getName(), errorEmailContent, currentLoginUser.getAccount());
                        if (!errorEmailResult) { //添加失败，给操作人发送邮件
                            String dingdingContent = active + "用户【" + newAccount.getAccount() + "】创建成功，发送短信、邮件失败,操作人手机号【" + currentLoginUser.getUserPhone()+ "】";
                            DingTalkUtil.exceptionSend(dingdingContent);
                        }
                    } else {
                        smsBizService.sendMessage(newAccount.getUserPhone(), SmsTemplateEnum.CREATE_OP_ACCOUNT_SUCCESS.getValue(), null, null);
                    }
                } else { //经销商发送邮件，发送短信
                    String emailContent = emailUtil.editorCreateDealerAccountSuccessContent(newAccount.getAccount(), password);
                    boolean sendResult = emailUtil.send(EmailSubjectEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getName(), emailContent, newAccount.getAccount());
                    if (!sendResult) { //添加失败，给操作人发送邮件
                        String errorEmailContent = emailUtil.editorCreateAccountErrorContent(SystemNameEnum.DEALER, newAccount.getRealName());
                        boolean errorEmailResult = emailUtil.send(newAccount.getRealName() + EmailSubjectEnum.CREATE_ACCOUNT_ERROR.getName(), errorEmailContent, currentLoginUser.getAccount());
                        if (!errorEmailResult) {
                            String dingdingContent = active + "用户【" + newAccount.getAccount() + "】创建成功，发送短信、邮件失败,操作人手机号【" + currentLoginUser.getUserPhone()+ "】";
                            DingTalkUtil.exceptionSend(dingdingContent);
                        }
                    } else {
                        smsBizService.sendMessage(newAccount.getUserPhone(), SmsTemplateEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getValue(), null, null);
                    }
                }
                //OP发送邮件，发送短信 end
                return result.success("成功", true);
            } else {
                return result.error("保存失败", false);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("保存失败");
    }

    /**
     * 添加新用户（车联网）
     *
     * @param account
     * @return
     */
    @Override
    public ResponseResult<Boolean> createIovAccount(IovAccountCreateVo account) {
        AccountCreateVo accountCreateVo = Convert.IovCreateAccountVoToAccountCreateVo(account);
        if (accountCreateVo != null) {
            accountCreateVo.setSystemType(SystemTypeEnum.OP.getValue());
        }

        ResponseResult<Boolean> result = validateCreateParam(accountCreateVo);
        if (result != null) {
            return result;
        }
        result = new ResponseResult<>();

        try {

            //查询账号是否存在
            Map<String, Object> getAccountCountParam = new HashMap<>();
            getAccountCountParam.put("account", accountCreateVo.getAccount());
            getAccountCountParam.put("systemType", SystemTypeEnum.OP.getValue());
            int count = accountService.getAccountCount(getAccountCountParam);
            if (count > 0) {
                logger.error("用户已经存在，无法重复保存，account is :: {}", accountCreateVo.getAccount());
                return result.error("保存失败，用户[" + accountCreateVo.getAccount() + "]已经存在");
            }

            AccountCreateDto newAccountDto = Convert.toAccountCreateDto(accountCreateVo);
            newAccountDto.setSystemType(SystemTypeEnum.OP.getValue());

            AccountDto iovAccount = accountService.getIovAccount();//查询车联网用户
            if (iovAccount != null) {
                newAccountDto.setAccountId(iovAccount.getId()); //操作人id
                newAccountDto.setAccountAccount(iovAccount.getRealName()); //操作人姓名
            }
            newAccountDto.setPasswordSalt(passwordSalt);

            int accountId = accountService.createAccount(newAccountDto);
            if (accountId > 0) {
                return result.success("保存成功", Boolean.TRUE);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("保存失败", Boolean.FALSE);

    }

    @Override
    public ResponseResult<Boolean> modifyAccount(AccountModifyVo account) {
        ResponseResult<Boolean> result = validateModifyParam(account);
        if (result != null) {
            return result;
        }
        result = new ResponseResult<>();

        try {
            //查询账号是否存在
            AccountDto oldAccount = accountService.getById(account.getId());
            if (oldAccount == null) {
                return result.error("修改失败，当前用户不存在", Boolean.FALSE);
            }

            UserEntity currentLoginUser = tokenUtil.getUser();

            AccountModifyDto accountDto = Convert.toAccountModifyDto(account);

            String password = "";
            //op用户修改后需要同步到车联网，而车联网是不可以修改邮箱的，所以目前op用户也不能修改邮箱，不然会导致数据一致性问题
            if (oldAccount.getSystemType().getValue() == SystemTypeEnum.DEALER.getValue() &&
                    ((oldAccount.getAccount() == null  && !StringUtil.isEmpty(account.getAccount())) || !oldAccount.getAccount().equals(account.getAccount()))) { //修改了邮箱
                //重新生成密码
                password = ApiUtils.generateNonceStrLower(8);
                accountDto.setPassword(Md5PwdEncoder.encodePassword(password, passwordSalt));

                Map<String, Object> getAccountCountParam = new HashMap<>();
                getAccountCountParam.put("account", account.getAccount());
                getAccountCountParam.put("systemType", account.getSystemType());
                int count = accountService.getAccountCount(getAccountCountParam);
                if (count > 0) {
                    logger.error("用户已经存在，无法重复保存，account is :: {}", account.getAccount());
                    return result.error("保存失败，用户[" + account.getAccount() + "]已经存在", Boolean.FALSE);
                }
            } else { //单独处理op用户
                accountDto.setAccount(oldAccount.getAccount());
            }

            accountDto.setAccountId(currentLoginUser.getAccountId()); //操作人id
            accountDto.setAccountAccount(currentLoginUser.getRealName()); //操作人名字
            accountBizService.modifyAccount(accountDto);
            //判断前后绑定角色是否一致，不一致则根据用户删除再添加
            if (account.getGroupId() != null && account.getGroupId() > 0 && !oldAccount.getIsSuper()) {
                accountGroupService.deleteByAccountId(account.getId()); //删除

                AccountGroupDto accountGroup = new AccountGroupDto();
                accountGroup.setAccountId(account.getId());
                accountGroup.setGroupId(account.getGroupId());
                accountGroup.setGmtCreate(LocalDateTime.now());
                accountGroupService.createBatchAccountGroup(accountGroup); //添加
            }

            if (account.getSystemType() == SystemTypeEnum.OP.getValue()) { //修改用户后，同步到车联网
                try {
                    IovModifyAccountDto iovModifyDto = new IovModifyAccountDto();
                    iovModifyDto.setAccount(account.getAccount());
                    iovModifyDto.setRealName(account.getRealName());
                    iovModifyDto.setRoleId(account.getIovGroupId());
                    iovModifyDto.setStatus(OpIovStatusConvertEnum.getIovValue(account.getStatus()));
                    iovModifyDto.setUserPhone(account.getUserPhone());
                    iovModifyDto.setAccount(oldAccount.getAccount()); //目前op用户不允许修改邮箱
                    ResponseResult<Boolean> iovResult = iovPermissionService.modifyAccount(iovModifyDto);
                    if (!iovResult.getCode().equals(ResponseCodeEnum.SUCCESS.getCode()) || !iovResult.getData()) { //同步失败
                        logger.error("修改用户失败，op修改用户成功，同步到车联网失败，用户id :: {}, 返回信息result ::{}", account.getId(), iovResult.getMessage());
                        return result.error("同步到车联网失败，车联网返回信息：" + iovResult.getMessage());
                    }
                } catch (Exception e) {
                    logger.error("修改用户失败，op添修改用户成功，同步到车联网失败，用户id :: {}", accountDto.getId());
                    logger.error(e.getMessage(), e);
                    return result.error("同步到车联网失败");
                }
            } else if (oldAccount.getSystemType().getValue() == SystemTypeEnum.DEALER.getValue() &&
                    ((oldAccount.getAccount() == null  && !StringUtil.isEmpty(account.getAccount())) || !oldAccount.getAccount().equals(account.getAccount()))) { // 修改了邮箱，发送短信
                JSONObject jsonObj = new JSONObject();
                jsonObj.put("useremail", account.getAccount());

                String emailContent = emailUtil.editorCreateDealerAccountSuccessContent(account.getAccount(), password);
                boolean sendResult = emailUtil.send(EmailSubjectEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getName(), emailContent, account.getAccount());
                smsBizService.sendMessage(account.getUserPhone(), SmsTemplateEnum.MODIFY_DEALER_ACCOUNT_SUCCESS.getValue(), jsonObj.toString(), null); //发送短信
            }
            tokenUtil.deleteUserByAccount(oldAccount); //强制登出

            result.setData(Boolean.TRUE);
            return result.success("成功", true);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("修改失败");
    }

    private void sendCreateOrModifyDealerAccountMessage(String account, String password, String realName, String userPhone) {
        String emailContent = emailUtil.editorCreateDealerAccountSuccessContent(account, password);
        boolean sendResult = emailUtil.send(EmailSubjectEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getName(), emailContent, account);
        if (!sendResult) {
            UserEntity currentLoginUser = tokenUtil.getUser();
            String errorEmailContent = emailUtil.editorCreateAccountErrorContent(SystemNameEnum.OP, realName);
            emailUtil.send(realName + EmailSubjectEnum.CREATE_ACCOUNT_ERROR.getName(), errorEmailContent, currentLoginUser.getAccount());
        } else {
            smsBizService.sendMessage(userPhone, SmsTemplateEnum.CREATE_DEALER_ACCOUNT_SUCCESS.getValue(), null, null); //发送短信
        }
    }

    @Override
    public ResponseResult<Boolean> modifyIovAccount(IovAccountModifyVo account) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        if (account == null) {
            logger.error("修改用户失败，用户为null，modify account is :: null");
            return result.error("修改用户失败", Boolean.FALSE);
        }

        if (StringUtil.isEmpty(account.getAccount())) {
            return result.error("修改用户失败，邮箱不能为空", Boolean.FALSE);
        }
        if (!ValidateUtil.isValidEmail(account.getAccount())) {
            return result.error("修改用户失败，邮箱格式错误", Boolean.FALSE);
        }

        if (StringUtil.isEmpty(account.getRealName())) {
            return result.error("修改用户失败，真实姓名不能为空", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(account.getUserPhone())) {
            return result.error("修改用户失败，手机号不能为空", Boolean.FALSE);
        }
        if (account.getUserPhone().length() != 11) {
            return result.error("修改用户失败，手机号格式错误", Boolean.FALSE);
        }

        try {
            accountService.modifyAccountByIov(Convert.toAccountDto(account));
            return result.success("修改成功", Boolean.TRUE);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("修改失败", Boolean.FALSE);
    }

    /**
     * 验证参数
     *
     * @param accountCreateVo
     * @return
     */
    private ResponseResult<Boolean> validateCreateParam(AccountCreateVo accountCreateVo) {
        ResponseResult<Boolean> result = new ResponseResult<>();
        result.setData(Boolean.FALSE);
        if (accountCreateVo == null) {
            logger.error("添加用户失败，用户为null，create account is :: null");
            return result.error("添加用户失败", Boolean.FALSE);
        }

        if (accountCreateVo.getSystemType() <= 0) {
            return result.error("添加用户失败，系统类型不能为空", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(accountCreateVo.getAccount())) {
            return result.error("添加用户失败，邮箱不能为空", Boolean.FALSE);
        }
        if (!ValidateUtil.isValidEmail(accountCreateVo.getAccount())) {
            return result.error("添加用户失败，邮箱格式错误", Boolean.FALSE);
        }
        if (accountCreateVo.getSystemType() == SystemTypeEnum.OP.getValue() && !accountCreateVo.getAccount().endsWith(opAccountSuffix)) {
            return result.error("添加用户失败，茉莉运营平台用户必须使用" +opAccountSuffix+ "结尾的邮箱格式", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(accountCreateVo.getRealName())) {
            return result.error("添加用户失败，真实姓名不能为空", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(accountCreateVo.getUserPhone())) {
            return result.error("添加用户失败，手机号不能为空", Boolean.FALSE);
        }
        if (accountCreateVo.getUserPhone().length() != 11) {
            return result.error("添加用户失败，手机号格式错误", Boolean.FALSE);
        }
        if (accountCreateVo.getSystemType() == SystemTypeEnum.DEALER.getValue() && accountCreateVo.getDealerId() <= 0) {
            return result.error("添加用户失败，经销商id不能为空", Boolean.FALSE);
        }

        return null;
    }

    /**
     * 验证参数
     *
     * @param account
     * @return
     */
    private ResponseResult<Boolean> validateModifyParam(AccountModifyVo account) {

        ResponseResult<Boolean> result = new ResponseResult<>();
        result.setData(Boolean.FALSE);
        if (account == null) {
            logger.error("修改用户失败，用户为null，modify account is :: null");
            return result.error("修改用户失败", Boolean.FALSE);
        }

        if (StringUtil.isEmpty(account.getAccount())) {
            return result.error("修改用户失败，邮箱不能为空", Boolean.FALSE);
        }
        if (!ValidateUtil.isValidEmail(account.getAccount())) {
            return result.error("修改用户失败，邮箱格式错误", Boolean.FALSE);
        }
        if (account.getSystemType() == SystemTypeEnum.OP.getValue() && !account.getAccount().endsWith(opAccountSuffix)) {
            return result.error("修改用户失败，茉莉运营平台用户必须使用" +opAccountSuffix+ "结尾的邮箱", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(account.getRealName())) {
            return result.error("修改用户失败，真实姓名不能为空", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(account.getUserPhone())) {
            return result.error("修改用户失败，手机号不能为空", Boolean.FALSE);
        }
        if (account.getUserPhone().length() != 11) {
            return result.error("修改用户失败，手机号格式错误", Boolean.FALSE);
        }
//        if (account.getId() <= 0) {
//            return result.error("修改用户失败，用户id不能为空", Boolean.FALSE);
//        }

        return null;
    }

    @Override
    public ResponseResult<Boolean> modifyResetPassword(AccountModifyVo vo) {

        ResponseResult<Boolean> result = new ResponseResult<>();
        result.setData(Boolean.FALSE);

        if (vo == null) {
            return result.error("参数不能为空");
        }
        if (vo.getId() <= 0) {
            return result.error("ID不能为空");
        }

        UserEntity currentLoginUser = tokenUtil.getUser();
        try {
            AccountDto account = accountService.getById(vo.getId());
            if (account == null) {
                return result.error("用户不存在");
            }

            String password = ApiUtils.generateNonceStrLower(8);
            account.setPassword(Md5PwdEncoder.encodePassword(password, passwordSalt));
            account.setAccountId(currentLoginUser.getAccountId()); //操作人id
            account.setAccountAccount(currentLoginUser.getRealName()); //操作人名字
            accountService.modifyAccount(account);

            tokenUtil.deleteUserByAccount(account.getAccount()); //强制登出


            //如果是op用户，修改密码后同步到车联网
            if (account.getSystemType().getValue() == SystemTypeEnum.OP.getValue()) {
                try {
                    ResponseResult<Boolean> iovResult = iovPermissionService.modifyPassword(account.getAccount(), Md5PwdEncoder.encodePassword(password,
                            passwordSalt));
                    if (!iovResult.getCode().equals(ResponseCodeEnum.SUCCESS.getCode()) || !iovResult.getData()) {
                        //同步失败
                        logger.error("重置密码失败，op重置密码成功，同步到车联网失败，用户id :: {}, 返回信息result ::{}", account.getId(), iovResult.getMessage());
                        return result.error("重置密码同步到车联网失败，车联网返回信息：" + iovResult.getMessage());
                    }
                } catch (Exception e) {
                    logger.error("重置密码失败，op重置密码成功，同步到车联网失败，用户id :: {}", account.getId());
                    logger.error(e.getMessage(), e);
                    return result.error("重置密码失败，op修改密码成功，同步到车联网失败");
                }
            }


            // 发短信/邮件通知重置密码
            if (account.getSystemType().getValue() == SystemTypeEnum.OP.getValue()) {
                // 发送邮件
                String content = emailUtil.editorResetPasswordContent(SystemNameEnum.OP_AND_IOV, account.getAccount(), password);
                boolean sendResult = emailUtil.send(EmailSubjectEnum.RESET_PASSWORD.getName(), content, account.getAccount());
                if (sendResult) {
                    smsBizService.sendMessage(account.getUserPhone(), SmsTemplateEnum.RESET_PASSWORD_BY_OP.getValue(), null, null); //发送短信
                }
            } else {
                // 发送邮件
                String content = emailUtil.editorResetPasswordContent(SystemNameEnum.DEALER, account.getAccount(), password);
                boolean sendResult = emailUtil.send(EmailSubjectEnum.RESET_PASSWORD.getName(), content, account.getAccount());
                if (sendResult) {
                    smsBizService.sendMessage(account.getUserPhone(), SmsTemplateEnum.RESET_PASSWORD_BY_DEALER.getValue(), null, null); // 发送短信
                }
            }


            return result.success("修改成功", Boolean.TRUE);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return result.error("修改失败");
    }

    @Override
    public ResponseResult<Boolean> modifyPassword(ModifyPassowrdVo vo) {
        ResponseResult<Boolean> result = new ResponseResult<Boolean>();

        if (vo == null) {
            return result.error("参数不能为空", Boolean.FALSE);
        }

        UserEntity user = tokenUtil.getUser();
        if (user != null) {
            int id = user.getAccountId();
            String oldPassword = vo.getOldPassword();
            String newPassword = vo.getNewPassword();


            if (StringUtil.isEmpty(oldPassword)) {
                return result.error("原密码不能为空", Boolean.FALSE);
            }
            if (StringUtil.isEmpty(newPassword)) {
                return result.error("新密码不能为空", Boolean.FALSE);
            }

            AccountDto account = accountService.getById(user.getAccountId());

            String salt = (!StringUtil.isEmpty(account.getPasswordSalt())) ? account.getPasswordSalt() : passwordSalt;
            oldPassword = Md5PwdEncoder.encodePassword(new String(Base64Utils.decodeFromString(oldPassword)), salt);
            newPassword = Md5PwdEncoder.encodePassword(new String(Base64Utils.decodeFromString(newPassword)), salt);



            if (!oldPassword.equals(account.getPassword())) {
                return result.error("原密码错误，请重新录入", Boolean.FALSE);
            }

            int row = accountService.modifyPassword(newPassword, id);
            if (row > 0) {
                tokenUtil.deleteUserByAccount(account.getAccount());

                //如果是op用户，修改密码后同步到车联网
                if (account.getSystemType().getValue() == SystemTypeEnum.OP.getValue()) {
                    try {
                        ResponseResult<Boolean> iovResult = iovPermissionService.modifyPassword(account.getAccount(), newPassword);
                        if (!iovResult.getCode().equals(ResponseCodeEnum.SUCCESS.getCode()) || !iovResult.getData()) {
                            //同步失败
                            logger.error("修改密码失败，op修改密码成功，同步到车联网失败，用户id :: {}, 返回信息result ::{}", account.getId(), iovResult.getMessage());
                            return result.error("同步到车联网失败，车联网返回信息：" + iovResult.getMessage());
                        }
                    } catch (Exception e) {
                        logger.error("修改密码失败，op修改密码成功，同步到车联网失败，用户id :: {}", account.getId());
                        logger.error(e.getMessage(), e);
                        return result.error("修改密码失败，op修改密码成功，同步到车联网失败");
                    }
                }

                return result.success("成功", Boolean.TRUE);
            } else {
                return result.error(ResponseCodeEnum.LOGIN_ERROR.getCode(), ResponseCodeEnum.LOGIN_ERROR.getMessage());
            }
        }


        return result.error("失败", Boolean.FALSE);
    }

    @Override
    public ResponseResult<Boolean> modifyPasswordByIov(IovAccountCreateVo vo) {

        ResponseResult<Boolean> result = new ResponseResult<Boolean>();
        if (vo == null) {
            return result.error("参数不能为空", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(vo.getAccount())) {
            return result.error("邮箱不能为空", Boolean.FALSE);
        }
        if (StringUtil.isEmpty(vo.getPassword())) {
            return result.error("邮箱不能为空", Boolean.FALSE);
        }

        int row = accountService.modifyPasswordByIov(vo.getPassword(), vo.getAccount());
        if (row > 0) {
            tokenUtil.deleteUserByAccount(vo.getAccount());
            return result.success("成功", Boolean.TRUE);
        }


        return result.error("失败", Boolean.FALSE);
    }

    @Override
    public void logOut() {
        UserEntity user = tokenUtil.getUser(); //当前登录用户
        if (user != null) {
            try {
                List<LoginLogDto> logOutLogList = loginLogService.getLogByAccountAndType(user.getAccount(), LoginLogTypeEnum.LOGOUT.getValue());
                if (CollectionUtils.isNotEmpty(logOutLogList)) { //更新
                    loginLogService.updateAccountLogOutTime(user.getAccount());
                } else { //添加
                    LoginLogDto log = new LoginLogDto();
                    log.setAccountId(user.getAccountId());
                    log.setAccountName(user.getAccount());
                    log.setGroupId(user.getGroupId());
                    log.setGroupName(user.getGroupName());
                    log.setLoginTime(LocalDateTime.now());
                    log.setType(LoginLogTypeEnum.LOGOUT.getValue());
                    loginLogService.createLoginLog(log);
                }
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
            tokenUtil.deleteCurrentUser();
        }

    }

    /**
     * 获取登录日志列表
     *
     * @param params
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public Paged<AccountLoginLogVo> getLoignLog(Map<String, Object> params, Integer pageNum, Integer pageSize) {
        Paged<AccountLoginLogVo> result = new Paged<>(new ArrayList<>(), 0, pageSize);
        // 查询登录日志
        params.put("type", "1");
        Paged<LoginLogDto> LoginLogDtoPage = loginLogService.getLoginLog(params, pageNum, pageSize);
        if (LoginLogDtoPage == null) {
            return result;
        }
        result.setTotal(LoginLogDtoPage.getTotal());
        result.setList(Convert.toAccountLoginLogVo(LoginLogDtoPage.getList()));

        return result;
    }

    @Override
    public ResponseResult<List<TabVo>> getTabList(Integer permissionId,Integer groupId) {
        ResponseResult<List<TabVo>> result = new ResponseResult<>();
        List<ResourceDto> allResourceList =  resourceService.getTabList(permissionId, SystemTypeEnum.OP.getValue(),null);
        if((null == allResourceList)||(allResourceList.size() == 0)) {
            return result.error(ResponseCodeEnum.NO_TAB.getCode(), ResponseCodeEnum.NO_TAB.getMessage());
        }
        List<ResourceDto> resourceList = resourceService.getTabList(permissionId, SystemTypeEnum.OP.getValue(),groupId);
        return result.success(Convert.toTabVo(resourceList));
    }

//    /**
//     * 同步车联网的登陆信息
//     * @param ssoToken
//     * @return
//     */
//    @Override
//    public ResponseResult<Boolean> syncIovLoginData(String ssoToken) {
//        ResponseResult<Boolean> result = new ResponseResult<Boolean>();
//        if (StringUtil.isEmpty(ssoToken))
//            return result.error("token不能为空", Boolean.FALSE);
//
//        String accountAccount = ssoTokenUtil.getAccountFromSsoToken(ssoToken); //解密token获取登陆名
//        if (StringUtil.isEmpty(accountAccount))
//            return result.error("登录名为空", Boolean.FALSE);
//
//        AccountDto account = accountService.getAccount(ssoToken, SystemTypeEnum.OP.getValue());
//        if (account == null)
//            return result.error("当前用户不存在", Boolean.FALSE);
//
//
//        return null;
//    }


}
